package com.rain.bucket;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ScreenUtils;
import com.badlogic.gdx.utils.viewport.FitViewport;

public class RainGame extends ApplicationAdapter {

    /* ========== 资源 ========== */
    private SpriteBatch spriteBatch;
    private FitViewport viewport; // 确保无论我们的窗口大小如何，完整的游戏视图始终可见
    private Texture dropTexture;
    private Texture goldDropTexture;
    private Texture bucketTexture;
    private Texture backgroundTexture;
    private BitmapFont font;

    /* ========== 雨滴对象 ========== */
    private static class Raindrop {
        Rectangle rect;
        boolean golden;   // true = 特殊雨滴
        int points;       // 普通 1 分，金色 3 分
        float speed;      // 普通 200，金色 400
    }

    private Rectangle bucket;
    private Array<Raindrop> raindrops;
    private float spawnTimer;

    /* ========== 分数系统 ========== */
    private int score;
    private int highScore;
    private Preferences prefs;

    /* ========== 常量 ========== */
    private static final int WORLD_WIDTH = 800;
    private static final int WORLD_HEIGHT = 480;
    private static final float BASE_SPEED = 200;
    private static final float GOLD_SPEED = 400;
    private static final float SPAWN_RATE = 1.0f;
    private static final float GOLD_CHANCE = 0.1f;   // 10% 概率

    @Override
    public void create() {
        /* --- 资源加载 --- */
        spriteBatch = new SpriteBatch();
        viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT);//让视口与世界坐标 1:1 对应
        viewport.getCamera().position.set(WORLD_WIDTH / 2f, WORLD_HEIGHT / 2f, 0);
        dropTexture = new Texture("drop.png");
        goldDropTexture = new Texture("goldDrop.png");
        bucketTexture = new Texture("bucket.png");
        backgroundTexture = new Texture("background.png");

        font = new BitmapFont();
        font.setColor(Color.WHITE);

        /* --- 桶初始化 --- */
        bucket = new Rectangle();
        bucket.width = 64;
        bucket.height = 64;
        bucket.x = WORLD_WIDTH / 2f - 64 / 2f;
        bucket.y = 20;

        /* --- 雨滴列表 --- */
        raindrops = new Array<>();

        /* --- 分数系统 --- */
        prefs = Gdx.app.getPreferences("rainbucket");
        highScore = prefs.getInteger("high", 0);
        score = 0;
    }

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height, true); // true centers the camera
    }

    @Override
    public void render() {

        /* --- 用户输入 --- */
        handleInput();

        logic();
        updateCamera();   // 让摄像机跟随桶
        /* --- 绘制 --- */
        draw();
    }


    private void logic() {
        /* --- 生成雨滴 --- */
        spawnTimer += Gdx.graphics.getDeltaTime();
        if (spawnTimer > SPAWN_RATE) {
            spawnTimer = 0;
            spawnRaindrop();
        }

        /* --- 更新雨滴 --- */
        updateRaindrops();
    }

    private void updateCamera() {
        // 只跟随桶的 x 坐标，y 保持居中
        float targetX = bucket.x + bucket.width / 2f;

        // 限制摄像机不超出世界边界
        float camHalfWidth = WORLD_WIDTH / 2f;
        float maxX = WORLD_WIDTH - camHalfWidth;
        targetX = MathUtils.clamp(targetX, camHalfWidth, maxX);

        viewport.getCamera().position.x = targetX;
        viewport.getCamera().update();  // 重要！更新矩阵
    }

    /* --- 绘制 --- */
    private void draw() {
        /* --- 清屏 --- */
        ScreenUtils.clear(Color.BLACK);

        viewport.apply();
        spriteBatch.setProjectionMatrix(viewport.getCamera().combined);//显示了视口如何应用于 SpriteBatch

        spriteBatch.begin();
        // 背景加载在桶前，跟随摄像机滚动
        spriteBatch.draw(backgroundTexture,
            viewport.getCamera().position.x - WORLD_WIDTH / 2f,
            0,
            WORLD_WIDTH,
            WORLD_HEIGHT);
        // 桶
        spriteBatch.draw(bucketTexture, bucket.x, bucket.y);

        // 雨滴
        for (Raindrop drop : raindrops) {
            Texture tex = drop.golden ? goldDropTexture : dropTexture;
            spriteBatch.draw(tex, drop.rect.x, drop.rect.y, 64, 64);
        }
        // 计数
        font.draw(spriteBatch, "Score: " + score, 10, WORLD_HEIGHT - 10);
        font.draw(spriteBatch, "Best: " + highScore, 10, WORLD_HEIGHT - 30);
        spriteBatch.end();
    }

    /* ========== 辅助方法 ========== */

    private void handleInput() {
        float delta = Gdx.graphics.getDeltaTime();
        float speed = 400;

        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) bucket.x -= speed * delta;
        if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) bucket.x += speed * delta;

        if (Gdx.input.isTouched()) {
            float touchX = viewport.unproject(new Vector2(Gdx.input.getX(), 0)).x;
            bucket.x = touchX - bucket.width / 2f;
        }

        // 允许桶穿墙并在对面出现
        if (bucket.x + bucket.width < 0) {
            bucket.x = WORLD_WIDTH;
        } else if (bucket.x > WORLD_WIDTH) {
            bucket.x = -bucket.width;
        }
    }


    private void spawnRaindrop() {
        boolean isGolden = MathUtils.random() < GOLD_CHANCE;

        Raindrop rd = new Raindrop();
        rd.rect = new Rectangle();
        rd.rect.width = 64;
        rd.rect.height = 64;
        rd.rect.x = MathUtils.random(0, WORLD_WIDTH - 64);
        rd.rect.y = WORLD_HEIGHT;

        rd.golden = isGolden;
        rd.speed = isGolden ? GOLD_SPEED : BASE_SPEED;
        rd.points = isGolden ? 3 : 1;

        raindrops.add(rd);
    }

    private void updateRaindrops() {
        float delta = Gdx.graphics.getDeltaTime();
        for (int i = 0; i < raindrops.size; ) {
            Raindrop rd = raindrops.get(i);
            rd.rect.y -= rd.speed * delta;

            if (rd.rect.y + rd.rect.height < 0) {
                raindrops.removeIndex(i);
            } else if (rd.rect.overlaps(bucket)) {
                raindrops.removeIndex(i);
                score += rd.points;
                if (score > highScore) {
                    highScore = score;
                    prefs.putInteger("high", highScore);
                    prefs.flush();
                }
            } else {
                i++;
            }
        }
    }

    @Override
    public void dispose() {
        spriteBatch.dispose();
        dropTexture.dispose();
        goldDropTexture.dispose();
        bucketTexture.dispose();
        font.dispose();
    }
}
